﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Diagnostics;


namespace Engine.Dtd.Schema {
    /// <summary>
    /// Represents a name of an SGML element, attribute or special reserved word.
    /// </summary>
    [DebuggerDisplay("{value}")]
    [DebuggerNonUserCode]
    public sealed class DName {
        [DebuggerBrowsable(DebuggerBrowsableState.Never)]
        private string value;

        /// <summary>
        /// Gets a DName object that represents the CDATA word.
        /// </summary>
        public static DName CData { get; internal set; }
        /// <summary>
        /// Gets a DName object that represents the PCDATA word.
        /// </summary>
        public static DName PCData { get; internal set; }

        /// <summary>
        /// Initialize a new instance of the DName class with specified name.
        /// </summary>
        /// <param name="name">The name of an SGML element or attribute.</param>
        internal DName(string name) {
            Guard.ArgumentNotNullOrEmpty(name, "name");
            this.value = name;
            }

        /// <summary>
        /// Returns a value indicating whether two instances of DName and string are equal.
        /// </summary>
        /// <param name="first">A first DName to compare.</param>
        /// <param name="second">A second DName to compare.</param>
        /// <returns>true if the <paramref name="first"/> and <paramref name="second"/> parameters represent the same DName object, otherwise, false.</returns>
        public static bool operator ==(DName first, DName second) {
            if (object.ReferenceEquals(first, second))
                return true;
            if (object.ReferenceEquals(first, null) || object.ReferenceEquals(second, null))
                return false;
            return object.ReferenceEquals(first.value, second.value);
            }

        /// <summary>
        /// Returns a value indicating whether two instances of DName and string are not equal.
        /// </summary>
        /// <param name="first">The first DName to compare.</param>
        /// <param name="second">The second DName to compare.</param>
        /// <returns>true if the <paramref name="first"/> and <paramref name="second"/> parameters represent different DName objects, otherwise, false.</returns>
        public static bool operator !=(DName first, DName second) {
            return !(first == second);
            }

        /// <summary>
        /// Converts a DName to a string object.
        /// </summary>
        /// <param name="name">A DName object.</param>
        /// <returns>A string that represent this object.</returns>
        public static implicit operator System.String(DName name) {
            if (object.ReferenceEquals(name, null))
                return null;
            else
                return name.value;
            }

        /// <summary>
        /// Determines whether this DName and the specified object are equal.
        /// </summary>
        /// <param name="obj">An object to compare to this instance.</param>
        /// <returns>true if <paramref name="obj"/> is a DName and equal to the current DName instance; otherwise, false.</returns>
        public override bool Equals(object obj) {
            DName name = obj as DName;
            if (object.ReferenceEquals(name, null))
                return false;
            else
                return object.ReferenceEquals(name, this);
            }

        /// <summary>
        /// Returns the hash code for this DName object.
        /// </summary>
        /// <returns>A 32-bit signed integer hash code.</returns>
        public override int GetHashCode() {
            return value.GetHashCode();
            }

        /// <summary>
        /// Returns the DTD name.
        /// </summary>
        /// <returns>A string that represents this instance.</returns>
        public override string ToString() {
            return value;
            }
        }
    }
